/*
 * Copyright (c) 2020 - present, Inspur Genersoft Co., Ltd.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *       http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package io.iec.edp.caf.rest;

import io.iec.edp.caf.commons.utils.SpringBeanUtils;
import io.iec.edp.caf.msu.common.manager.AppManager;
import io.iec.edp.caf.rest.server.RESTEndpointUtil;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.apache.cxf.Bus;
import org.apache.cxf.endpoint.Server;

import java.util.*;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author wangyandong
 */
@Deprecated
@Slf4j
//todo 被com.inspur.gs.gsp.sys.securitylevel.config.ExternalApiConfiguration依赖，命名空间无法调整
public class RESTEndpointRegistrar {
    @Getter
    private Map<String, RESTEndpoint> endPoints;

    private Bus bus;

    private Set<String> suRegistry;
    private Set<String> pathRegistry;
    private Lock lock = new ReentrantLock();
    private Lock lock4EndPoints = new ReentrantLock();

    public RESTEndpointRegistrar(Bus bus) {
        this.pathRegistry = new HashSet<>();
        this.bus = bus;
        this.suRegistry = new HashSet<>();
        this.endPoints = new HashMap<>();
//        this.endPoints = new HashMap<>();
//        this.endPoints = list.stream().collect(Collectors.toMap(RESTEndpoint::getPath, a -> a,(k1, k2)->k1));
    }

    /**
     * 判断路径是否已经注册EndPoint
     *
     * @param path
     * @return
     */
    public Boolean isRegistered(String path) {
//        if(destinationRegistry==null){
//            this.bus = SpringBeanUtils.getBean(Bus.class);
//            this.destinationRegistry = bus.getExtension(HTTPTransportFactory.class).getRegistry();
//        }
////        String pathInfo = request.getPathInfo() == null ? "" : request.getPathInfo();
//        AbstractHTTPDestination d = this.destinationRegistry.checkRestfulRequest(path);
//        return d!=null;

        Boolean registered = false;
        try {
            lock.lock();
            if (pathRegistry.contains(path)) {
                registered = true;
            }
        } catch (Exception e) {
            log.error(e.getMessage(),e);
        } finally {
            lock.unlock();
        }
        return registered;
    }

    /**
     * 根据请求路径返回对应的RESTEndpoint
     *
     * @param su
     * @param address
     * @return
     */
    public RESTEndpoint findRESTEndpoint(String su, String address) {
        RESTEndpoint endpoint = null;
        address = this.getTrimmedPath(address);

        //递归查找
        RESTEndpoint ret = null;
        String thePath = address;
        Map<String, RESTEndpoint> points = this.getRestEndPoints(su);
        while (points != null && thePath != null && thePath.length() > 1 && ret == null) {
            if (points.containsKey(thePath)) {
                ret = points.get(thePath);
            } else {
                thePath = thePath.substring(0, thePath.lastIndexOf("/"));
            }
        }

        return ret;
    }

    /**
     * 注册Server
     *
     * @param endpoint
     * @return
     */
    public Server register(RESTEndpoint endpoint, String pathInfo) {
        if (endpoint == null)
            return null;

        try {
            lock.lock();
            if (pathRegistry.contains(endpoint.getPath())) {
                return null;
            } else {
                pathRegistry.add(endpoint.getPath());
                RESTServiceRegistrar.getSingleton().putEndpoints(Arrays.asList(endpoint));
                return RESTEndpointUtil.createJAXRSServer(endpoint.getPath(), this.bus, endpoint.getServices());
            }
        } catch (Exception e) {
            log.error(e.getMessage(),e);
            return null;
        } finally {
            lock.unlock();
        }
    }

    /**
     * 注销Server
     *
     * @param path
     * @return
     */
    public Boolean unregister(String path) {
        try {
            lock.lock();
            if (!pathRegistry.contains(path)) {
                return false;
            } else {
                pathRegistry.remove(path);
                return true;
            }
        } finally {
            lock.unlock();
        }
    }

    public String getTrimmedPath(String path) {
        if (path == null) {
            return "/";
        } else {
            String lh = "http://localhost/";
            String lhs = "https://localhost/";
            if (path.startsWith("http://localhost/")) {
                path = path.substring("http://localhost/".length());
            } else if (path.startsWith("https://localhost/")) {
                path = path.substring("https://localhost/".length());
            }

            if (!path.contains("://") && !path.startsWith("/")) {
                path = "/" + path;
            }

            return path;
        }
    }

    public Map<String, RESTEndpoint> getRestEndPoints(String su) {
        if (this.suRegistry.contains(su))
            return this.endPoints;

        try {
            lock4EndPoints.lock();
            if (!this.suRegistry.contains(su)) {

                Set<String> names = AppManager.getBeanNames(su.toLowerCase(), RESTEndpoint.class);
                if (names != null && names.size() > 0) {
                    for (String beanName : names) {
                        RESTEndpoint endpoint = SpringBeanUtils.getBean(beanName, RESTEndpoint.class);
                        if (endpoint != null)
                            this.endPoints.put(endpoint.getPath(), endpoint);
                    }
                }
                this.suRegistry.add(su);
            }
        } catch (Exception e) {
            log.error(e.getMessage(),e);
            return null;
        } finally {
            lock4EndPoints.unlock();
        }

        return this.endPoints;
    }
}
